import axios from 'axios'
import { Message } from 'element-ui'
import store from '@/store'
import router from '@/router'
import { getTimeStamp } from './auth'
// #1 如果想后面的弹框覆盖前面的弹框，用这个 message 替换掉原来的 Message
// #2 如果组件当中使用 this.$message 这种方式弹框，也只想出来一次，需要在 main.js 做如下操作。
import { message } from '@/utils/resetMessage'
// Vue.prototype.$message = message
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API,
  timeout: 5000
})

const IsCheckTimeOut = () => {
  return (Date.now() - getTimeStamp()) / 1000 > TIME
}

const TIME = 3600 // 秒

// 请求拦截器，统一携带 token，简化后续发请求的代码
service.interceptors.request.use((config) => {
  // config => 请求对象
  if (store.getters.token) {
    config.headers['Authorization'] = `Bearer ${store.getters.token}`
    // !#3
    // 用当前时间 - 登录时候记住的时间 > TOKEN 有效时间
    // 说明过期了
    // 做退出相关的操作
    // if ((Date.now() - getTimeStamp()) / 1000 > TIME) {
    if (IsCheckTimeOut()) {
      // 过期了
      store.dispatch('user/logout')
      router.push('/login')
      // 返回一个错误的 Promise
      return Promise.reject(new Error('Token 过期了'))
    }
  }
  // 一定不要忘记返回 config
  return config
}, (error) => {
  // 默认的
  return Promise.reject(error)
})

// 响应拦截器：对后端返回的数据进行一次加工处理后再给真正发请求的地方

service.interceptors.response.use((response) => {
  // response => 就是后端返回的数据
  // 这儿 return 啥，真正发请求的地方就能拿到啥，默认 return response
  const { success, message, data } = response.data
  if (success) {
    return data
  } else {
    // Message.error(message)
    Message({
      type: 'error',
      message,
      offset: 100
    })
    // 业务失败了，记得也要返回一个错误的 Promise
    return Promise.reject(new Error(message))
  }
}, error => {
  // 极端情况下，error.response 可能是 undefined，如果是 undefined 的话，从 undefined 上读 data 就会程序报错
  // if (error.response.data.code === 10002) {
  // if (error.response && error.response.data && error.response.data.code === 10002) {
  if (error.response?.data?.code === 10002) {
    // TOKEN 过期了，无效的 TOKEN
    store.dispatch('user/logout')
    router.push('/login')
    Message.error('Token 过期了')
    // 返回一个错误的 Promise
    // return Promise.reject(new Error('Token 过期了'))
  } else {
    // 失败的时候会触发，例如 4xx 状态，5xx
    // message.error(error.message)
    Message.closeAll()
    Message.error(error.message)
  }
  // 这儿一定记得返回一个错误的 Promise
  return Promise.reject(error)
})

export default service
